package com.samsung.sharepoint;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.DhcpInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

//This Activity is responsible for handling and viewing devices online in the Wi-Fi
public class ChatList extends Activity {
	
	/*ArrayList<String> myList = new ArrayList<String>();*/
	ArrayAdapter<String> adapter;
	private byte[] quads;
	private String data;
	private DatagramSocket socket;
	private boolean send= true; 
	ArrayList<String> IpAddressList;
	ArrayList<String> HostNameList;
	ListView list;
    private SharedPreferences spref;
	private String myUserName;  
	String myIP = "/" + getLocalIpAddress(); //Obtain the IPAddress of your working device
	
	
	/*The BroadcastReceiver receives broadcast intent from ServiceClass.java(udp broadcast listener server.
	 *  The intent received has IPAddress and name of the udp broadcast sender as its parameter.
	 */
	 private BroadcastReceiver IPReceiver = new BroadcastReceiver() {
	        @Override
	        public void onReceive(Context context, Intent intent) {
	    		String IpAddress = intent.getStringExtra("IpAddress");
	    		String sender = intent.getStringExtra("Sender");
	    		if(!myIP.contentEquals(IpAddress) && isNotDuplicate(sender+IpAddress)){
	    			/*If the IPAddress received is not of its own device AND the IPAddress has aldready not been stored in 
	    			 * the ArrayList, then add the intent's parameter in ArrayList.
	    			 */
	    			if(!sender.equals("Anonymous Pundit")){ //If the name sent does not have default name
	    				nameListAdapter.add(sender+IpAddress);
	    			}
	    		}
	        }
	    };
	    
	
	private TextView t2;
	private ArrayList<String> nameList;
	private ArrayAdapter<String> nameListAdapter;
	private ListView listView;
	
	    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d("ChatList","OnCreate");
		super.onCreate(savedInstanceState);
		
		Intent intent=new Intent("com.samsung.sharepoint.serviceclass");
		Log.d("ChatList","Service Started");
		startService(intent); //This Service is responsible for listening to udp broadcast messages sent by other devices
		
		setContentView(R.layout.available);
		spref = getSharedPreferences("abc",MODE_PRIVATE); //This Shared Preference stores the User's name of this device
        
		nameList = new ArrayList<String>(); //This ArrayList will store all the device's name in Wi-Fi
		nameListAdapter = new ArrayAdapter<String>(this,R.layout.layout, nameList); //Obtain ArrayAdapter for TextView in "layout.xml" populated with "nameList" elements
		listView = (ListView) findViewById(R.id.listView1); //Obtain the reference for ListView in "available.xml"
		listView.setAdapter(nameListAdapter);  //Populate the ListView with ArrayAdapter
      
     	registerReceiver(IPReceiver, new IntentFilter(listenService.BROADCAST_ACTION));
     	//Register the BroadcastReceiver "IPReceiver" with the broadcast intent of type "listenService.BROADCAST_ACTION"
		
     	if(send){ //send is to ensure that Broadcast is sent only once
			spref = getSharedPreferences("abc",MODE_PRIVATE);
			myUserName = spref.getString("name", "Anonymous Pundit"); //Obtain the User Name of your device
		    sendBroadcast(); //Send the Broadcast, that will be handled and received by IPReceiver in this file
			send=false;
		}
		
     	/* If any one one device in the list item is clicked, then obtain that device's IP Address and it's UserName, 
     	 * and then put those values as parameter for intent t invoke Activity "SampleTCP.java"
     	 */
		listView.setOnItemClickListener(new OnItemClickListener() { 
			private String ip;

			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
		        Log.d("ChatList"," After Click IP");
				ip = ((TextView) arg1).getText().toString();
				
				String name = ip.substring(0, ip.indexOf("/")); //Obtain the UserName of the device selected
		        ip = ip.substring(ip.indexOf("/")+1); //Obtain the IP Address of the device selected
		        
		        Intent intent=new Intent("com.samsung.activity.SampleTCP");
		 		intent.putExtra("AvailableDeviceIP", ip); 
		 		intent.putExtra("SampleTCP_UserName_Receiver", name);
		 		startActivity(intent); //Activity "SampleTCP.java" is invoked with the IPAddress and the device name obtained
			}
        	
		});
       }
	
// This function is to check if the passed string is aldready present in ArrayList "nameList"
	protected boolean isNotDuplicate(String uid) {
		for(int i=0;i<nameList.size();i++)
			if(nameList.get(i).equals(uid)){
				return false;
			}
		return true;
	}

	@Override
	public void onStart(){
		super.onStart();
	}

	@Override
	protected void onResume(){
		String str1;
		//Set the values of TextView in "available.xml" to present the Activity's welcome screen
	    t2 = (TextView) findViewById(R.id.textView2);
	    t2.setText(Html.fromHtml("<Font color='#cccccc'><b><i>" + this.getString(R.string.welcome) + " </i></b></font>"));
	    str1 = spref.getString("name","nothing");
        t2.append(Html.fromHtml("<Font color='#cccccc'><b><i>"+str1+" !!!</i></b></font>"));
        t2.setTextSize(30);
        
		/*registerReceiver(IPReceiver, new IntentFilter(listenService.BROADCAST_ACTION));*/
		super.onResume();
		Log.d("ChatList",myIP + " " + myIP.length());
		Log.d("ChatList", "MyIP and its length " +  myIP + " " + myIP.length());
	    Log.d("ChatList","onResume()");
		
	}
	
	
    @Override
	protected void onStop(){
    	//Stop all the running services except "udp broadcast listener" service
		Intent intent1=new Intent("com.samsung.sharepoint.serviceclientclass");
    	stopService(intent1);
    	Intent file_client_intent=new Intent("com.samsung.sharepoint.fileclientservice");
    	stopService(file_client_intent);
    	Intent chat_server_intent=new Intent("com.samsung.sharepoint.serviceclass");
    	stopService(chat_server_intent);
    	Intent file_server_intent=new Intent("com.samsung.sharepoint.fileserverservice");
    	stopService(file_server_intent);
    	
		super.onStop();
	}
    
	
//This method is used to send udp broadacst to all the devices the Wi-Fi
    public void sendBroadcast(){

		try {
			data = myUserName; //myUserName stores the UserName of your device
			socket = new DatagramSocket();
			DatagramPacket packet = new DatagramPacket(data.getBytes(),	data.length(), getBroadcastAddress(), 4456);
			Log.d("com.samsung.sharepoint", getBroadcastAddress().getHostAddress());
			socket.setSoTimeout(100);
			socket.send(packet);
		} 
		
		//On receiving exception, display appropriate dialog box for user's response
		
		catch (UnknownHostException e) {
			new AlertDialog.Builder(ChatList.this)
    	    .setTitle("Cannot Find Host")
    	    .setMessage("Cannot find the user")
    	    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    	        	public void onClick(DialogInterface dialog, int whichButton) {
    	        		//Stop all the running services except "udp broadcast listener" service
    	        		Intent intent1=new Intent("com.samsung.sharepoint.serviceclientclass");
    	            	stopService(intent1);
    	            	Intent file_client_intent=new Intent("com.samsung.sharepoint.fileclientservice");
    	            	stopService(file_client_intent);
    	            	Intent chat_server_intent=new Intent("com.samsung.sharepoint.serviceclass");
    	            	stopService(chat_server_intent);
    	            	Intent file_server_intent=new Intent("com.samsung.sharepoint.fileserverservice");
    	            	stopService(file_server_intent);
    	            	System.exit(0);
    	        	}
    	    })
    	    .create()
    	    .show();
			e.printStackTrace();
		} catch (SocketException e) {
			new AlertDialog.Builder(ChatList.this)
    	    .setTitle("Network Failure")
    	    .setMessage("Check your network connection")
    	    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    	        	public void onClick(DialogInterface dialog, int whichButton) {
    	        		//Stop all the running services except "udp broadcast listener" service
    	        		Intent intent1=new Intent("com.samsung.sharepoint.serviceclientclass");
    	            	stopService(intent1);
    	            	Intent file_client_intent=new Intent("com.samsung.sharepoint.fileclientservice");
    	            	stopService(file_client_intent);
    	            	Intent chat_server_intent=new Intent("com.samsung.sharepoint.serviceclass");
    	            	stopService(chat_server_intent);
    	            	Intent file_server_intent=new Intent("com.samsung.sharepoint.fileserverservice");
    	            	stopService(file_server_intent);
    	            	System.exit(0);
    	        	}
    	    })
    	    .create()
    	    .show();
			e.printStackTrace();
		} catch (IOException e) {
			new AlertDialog.Builder(ChatList.this)
    	    .setTitle("IOException")
    	    .setMessage(e.toString())
    	    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    	        	public void onClick(DialogInterface dialog, int whichButton) {
    	        		//Stop all the running services except "udp broadcast listener" service
    	        		Intent intent1=new Intent("com.samsung.sharepoint.serviceclientclass");
    	            	stopService(intent1);
    	            	Intent file_client_intent=new Intent("com.samsung.sharepoint.fileclientservice");
    	            	stopService(file_client_intent);
    	            	Intent chat_server_intent=new Intent("com.samsung.sharepoint.serviceclass");
    	            	stopService(chat_server_intent);
    	            	Intent file_server_intent=new Intent("com.samsung.sharepoint.fileserverservice");
    	            	stopService(file_server_intent);
    	            	System.exit(0);
    	        	}
    	    })
    	    .create()
    	    .show();
			e.printStackTrace();
		}
	}
	
	
    //This method invokes the udp broadacst address, so as to send to all devices in the Wi-Fi
	public InetAddress getBroadcastAddress() throws UnknownHostException {
		WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		//WifiManager provides for managing all aspects of Wi-Fi Connectivity
		DhcpInfo dhcp = wifi.getDhcpInfo();
		//"getDhcpInfo" returns the DHCP-assigned addresses from the last successful DHCP request
		int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
		/* "dhcp.ipAddress & dhcp.netmask" results in all non-network id bits to be '0'
		 * and then Or-ing with "~dhcp.netmask" results in all network id bits to be '1', and hennce obtaining broadcast address
		 */
		quads = new byte[4];
		for (int k = 0; k < 4; k++)
			quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); //Obtain every byte and store it in byte-array
		
		return InetAddress.getByAddress(quads);
	}  
	
	
	public void onDestroy() {
		socket.close();
		super.onDestroy();
	}
	
    // This method gets IP Address of your deivice
	private String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            	//en contains the enumeration of all Network interfaces 
            	NetworkInterface intf = en.nextElement();
                //Obtain every Network Interface from enumeration "en"
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); }
                }
            }
        } catch (SocketException ex) {
        	new AlertDialog.Builder(ChatList.this)
    	    .setTitle("IOException")
    	    .setMessage(ex.toString())
    	    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    	        	public void onClick(DialogInterface dialog, int whichButton) {
    	        		//Stop all the running services except "udp broadcast listener" service
    	        		Intent intent1=new Intent("com.samsung.sharepoint.serviceclientclass");
    	            	stopService(intent1);
    	            	Intent file_client_intent=new Intent("com.samsung.sharepoint.fileclientservice");
    	            	stopService(file_client_intent);
    	            	Intent chat_server_intent=new Intent("com.samsung.sharepoint.serviceclass");
    	            	stopService(chat_server_intent);
    	            	Intent file_server_intent=new Intent("com.samsung.sharepoint.fileserverservice");
    	            	stopService(file_server_intent);
    	            	System.exit(0);
    	        	}
    	    })
    	    .create()
    	    .show();
        	Log.e("ServerActivity", ex.toString());
        }
        return null;
    }
    
	
	/*Create a Menu option to give option to user so that User-Name of the device can be changed
	 * and/or start or stop the udp broadacst listen service (listenService.java)
	 */
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	MenuInflater inflater = getMenuInflater();
    	inflater.inflate(R.menu.use_name_menu_control, menu);
    	return true;
    }
    
	//This method is invoked if any one of the menu item is clicked
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch(item.getItemId()){
    	case R.id.changeUserName:
    		Intent intent = new Intent(getBaseContext(),first.class);
        	startActivity(intent);  //Start Activity "first.java" so that User could change User-Name for the device
        	break;
    	case R.id.listenServiceSettings:
    		Intent intent1 = new Intent(getBaseContext(),listenServiceNotification.class);
        	startActivity(intent1);
        	break; //Start the Activity "listenServiceNotification.java" so as to give option to start or stop udp broadacst listen service
    	default:
    	}
    	return super.onOptionsItemSelected(item);
    	
    }
}
